<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="shortcut icon" type="image/svg+xml"
        href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20100%20100'%3E%3Ctext%20y='.9em'%20font-size='90'%3E♾️%3C/text%3E%3C/svg%3E">
    <title>GPG公钥解析工具</title>
    <script src="https://cdn.jsdelivr.net/npm/openpgp@5.11.0/dist/openpgp.min.js"></script>
    <style>
        body {
            font-family: 'Segoe UI', Arial, sans-serif;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            line-height: 1.6;
            background-color: #f5f5f5;
        }

        .container {
            background: white;
            padding: 30px;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        }

        h1 {
            color: #333;
            border-bottom: 2px solid #4CAF50;
            padding-bottom: 10px;
        }

        .input-section {
            margin-bottom: 20px;
        }

        textarea {
            width: 100%;
            height: 200px;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-family: monospace;
            resize: vertical;
        }

        button {
            background-color: #4CAF50;
            color: white;
            border: none;
            padding: 12px 20px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
        }

        button:hover {
            background-color: #45a049;
        }

        .output-section {
            margin-top: 20px;
            padding: 20px;
            background-color: #f9f9f9;
            border-radius: 4px;
            border: 1px solid #ddd;
        }

        .metadata-item {
            margin-bottom: 10px;
        }

        .metadata-label {
            font-weight: bold;
            color: #2c3e50;
        }

        .error {
            color: #e74c3c;
            padding: 10px;
            background-color: #fadbd8;
            border-radius: 4px;
        }
    </style>
</head>

<body>
    <div class="container">
        <h1>GPG公钥解析工具</h1>
        <div class="input-section">
            <h2>输入ASCII Armored格式的GPG公钥</h2>
            <textarea id="publicKeyInput" placeholder="-----BEGIN PGP PUBLIC KEY BLOCK-----..."></textarea>
            <br><br>
            <button id="parseButton">解析公钥</button>
        </div>
        <div class="output-section" id="outputSection">
            <h2>公钥元信息</h2>
            <div id="metadataOutput"></div>
        </div>
    </div>

    <script>
        document.getElementById('parseButton').addEventListener('click', async () => {
            const input = document.getElementById('publicKeyInput').value;
            const outputDiv = document.getElementById('metadataOutput');
            outputDiv.innerHTML = '';

            try {
                if (!input.trim()) {
                    throw new Error('请输入有效的ASCII Armored GPG公钥');
                }

                // 解析公钥
                const publicKey = await openpgp.readKey({ armoredKey: input });

                // 提取元信息
                // 提取所有密钥信息（主密钥和子密钥）
                const keys = publicKey.getKeys();
                const primaryKey = keys[0];
                const subkeys = keys.slice(1);

                const primaryKeyId = primaryKey.getKeyID().toHex().toUpperCase();
                const creationTime = new Date(primaryKey.getCreationTime()).toLocaleString();
                const algorithm = primaryKey.getAlgorithmInfo().algorithm;
                const bitLength = primaryKey.getAlgorithmInfo().bits;
                const userIds = publicKey.getUserIDs();
                const fingerprint = primaryKey.getFingerprint().toUpperCase();
                // 日期格式化辅助函数 - 修复Invalid Date问题
                const formatExpirationTime = async (expiration) => {
                    try {
                        const timestamp = await expiration;
                        if (timestamp === Infinity) { return '永不过期' }

                        // 统一转换为毫秒时间戳
                        const parsedTimestamp = typeof timestamp === 'number'
                            ? (timestamp.toString().length <= 10 ? timestamp * 1000 : timestamp)
                            : timestamp;

                        const date = new Date(parsedTimestamp);
                        return isNaN(date.getTime()) ? '无效日期' : date.toLocaleString();
                    } catch (error) {
                        console.error('日期格式错误:', error);
                        return '无效日期';
                    }
                };

                const shortId = primaryKeyId.slice(-8); // 提取shortID（后8位）
                const expirationTime = await formatExpirationTime(primaryKey.getExpirationTime());

                // 解析用户标识和邮箱
                let userName = '未提供';
                let userEmail = '未提供';
                if (userIds.length > 0) {
                    const userIdParts = userIds[0].match(/^(.*?)(?:\s+<(.*?)>)?$/);
                    if (userIdParts) {
                        userName = userIdParts[1] || '未提供';
                        userEmail = userIdParts[2] || '未提供';
                    }
                }

                // 构建子密钥HTML
                let subkeysHtml = '';
                if (subkeys.length > 0) {
                    subkeysHtml = '<div class="subkeys"><h4>子密钥信息</h4>';
                    for (const subkey of subkeys) {
                        const subkeyId = subkey.getKeyID().toHex().toUpperCase();
                        const subkeyAlg = subkey.getAlgorithmInfo().algorithm;
                        const subkeyBits = subkey.getAlgorithmInfo().bits;
                        const subkeyCreation = new Date(subkey.getCreationTime()).toLocaleString();
                        const subkeyExpiration = await formatExpirationTime(subkey.getExpirationTime());
                        const subkeyShortId = subkeyId.slice(-8);
                        subkeysHtml += `
                            <div class="subkey">
                                <div><strong>子密钥ID:</strong> ${subkeyId}</div>
                                <div><strong>Short ID:</strong> ${subkeyShortId}</div>
                                <div><strong>算法:</strong> ${subkeyAlg} (${subkeyBits}位)</div>
                                <div><strong>创建时间:</strong> ${subkeyCreation}</div>
                                <div><strong>有效期:</strong> ${subkeyExpiration}</div>
                            </div>
                            <br/>
                        `;
                    };
                    subkeysHtml += '</div>';
                }

                // 构建HTML输出
                let metadataHtml = `
                    <div class="metadata">
                        <h3>公钥信息</h3>
                        <div><strong>用户标识:</strong> ${userName}</div>
                        <div><strong>邮箱:</strong> ${userEmail}</div>
                        <div><strong>主密钥ID:</strong> ${primaryKeyId}</div>
                        <div><strong>Short ID:</strong> ${shortId}</div>
                        <div><strong>指纹:</strong> ${fingerprint}</div>
                        <div><strong>创建时间:</strong> ${creationTime}</div>
                        <div><strong>有效期:</strong> ${expirationTime}</div>
                        <div><strong>算法:</strong> ${algorithm} (${bitLength}位)</div>
                        ${subkeysHtml}
                    </div>
                `;

                outputDiv.innerHTML = metadataHtml;
            } catch (error) {
                outputDiv.innerHTML = `<div class="error">解析错误: ${error.message}</div>`;
                console.error('解析失败:', error);
            }
        });
    </script>
</body>

</html>